#include "MyMsgPack.h"
#include "stddef.h"

void Encode( const char* pcData,int iLen,char* pcResult,int& riLen )
{
	if (pcData == NULL || iLen <= 0)
	{
		return;
	}

	if (pcResult == NULL)
	{
		return;
	}

	for (int i = 0;i < iLen;i++)
	{
		pcResult[i] = ((BYTE(pcData[i])) << 4) | ((BYTE(pcData[i])) >> 4);
	}

	riLen = iLen;
	return;
}

void Decode( const char* pcData,int iLen,char* pcResult,int& riLen )
{
	Encode(pcData,iLen,pcResult,riLen);
	return;
}

BYTE CalCheck( const BYTE abyData[],int iLen )
{
	if (abyData == NULL || iLen <= 0)
	{
		return 0;
	}

	BYTE byRet = 0;
	for (int i = 0;i < iLen;i++)
	{
		byRet ^= abyData[i];
	}

	return byRet;
}

bool CheckHead( const char* pcData,int iLen )
{
	if (pcData == NULL || iLen <= 0)
	{
		return false;
	}

	if (iLen < sizeof(MyPackHead))
	{
		return false;
	}

	const MyPackHead* pkHead = (MyPackHead*)pcData;
	if (memcmp(pkHead->cHead,"QXY",3) != 0)
	{
		return false;
	}

	if (CalCheck((BYTE*)pcData,offsetof(MyPackHead,byCheck)) != pkHead->byCheck)
	{
		return false;
	}

	return true;
}

void PackMsg(MyDataPack& rkPack, const char* pcData,int iLen,bool bEncrypt /*= false*/ )
{
	if (pcData == NULL || iLen <= 0)
	{
		return;
	}

	if (iLen > MAX_MSG_LEN)
	{
		return;
	}

	int iResult = 0;
	const char* pBuf = NULL;
	char acBuf[MAX_MSG_LEN * 2] = {0};

	if (bEncrypt)
	{
		Encode(pcData,iLen,acBuf,iResult);
		pBuf = acBuf;
	}
	else
	{
		pBuf = pcData;
		iResult = iLen;
	}

	MyPackHead* pkHead = (MyPackHead*)(rkPack.acData);
	memcpy(pkHead->cHead,"QXY",3);
	pkHead->bEncrypt = bEncrypt;
	pkHead->iLength = iResult;
	pkHead->iRand = rand() % INT_MAX;
	pkHead->byCheck = CalCheck((BYTE*)pkHead,offsetof(MyPackHead,byCheck));
	ZeroMemory(pkHead->byReserved,sizeof(pkHead->byReserved));

	memcpy(pkHead + 1,pBuf,iResult);
	rkPack.iLen = sizeof(MyPackHead) + iResult;

	return;
}

ParsePackError ParsePack( MyDataPack& rkPack,const char* pcData,int iLen )
{
	if (pcData == NULL || iLen <= 0)
	{
		return PPE_PARAM_INVALID;
	}

	if (iLen < sizeof(MyPackHead))
	{
		return PPE_WAIT_FOR_DATA;
	}

	if (!CheckHead(pcData,iLen))
	{
		return PPE_CHECK_HEAD_ERROR;
	}

	const MyPackHead* pkHead = (MyPackHead*)pcData;
	int iMsgLength = pkHead->iLength;
	if (iMsgLength > MAX_MSG_LEN)
	{
		iMsgLength = MAX_MSG_LEN;
	}

	if (iMsgLength > iLen - sizeof(MyPackHead))
	{
		return PPE_WAIT_FOR_DATA;
	}

	int iReaLen = iMsgLength;
	if (pkHead->bEncrypt)
	{
		Decode((char*)(pkHead + 1),iMsgLength,rkPack.acData,iReaLen);
	}
	else
	{
		memcpy(rkPack.acData,(char*)(pkHead + 1),iReaLen);
	}
	rkPack.iLen = iReaLen;

	return PPE_NO_ERROR;
}